package com.xinghen.common.core.util;

import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.xinghen.common.base.GlobalConstant;
import com.xinghen.common.base.enums.ErrorType;
import com.xinghen.common.base.exception.BusinessException;
import com.xinghen.common.base.model.dto.LoginUser;
import com.xinghen.common.util.ThreadContextHolder;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Base64;
import java.util.Objects;

/**
 * @author xinghen
 * @ClassName: RequestUtil
 * @Package: com.xinghen.common.core.utils
 * @Description request 工具
 * @create 2018-04-13 11:44
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class RequestUtil {

    /**
     * 获取当前的 HttpServletRequest
     *
     * @return
     */
    public static HttpServletRequest currentRequest() {
        RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
        Preconditions.checkNotNull(attributes, "无法获取到HttpServletRequest");
        return ((ServletRequestAttributes) attributes).getRequest();
    }

    /**
     * 获取用户IP地址
     *
     * @param request
     * @return
     */
    public static String getRemoteAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader(GlobalConstant.Request.X_REAL_IP);
        if (!isValidIp(ipAddress)) {
            ipAddress = request.getHeader(GlobalConstant.Request.X_FORWARDED_FOR);
        }
        if (!isValidIp(ipAddress)) {
            ipAddress = request.getHeader(GlobalConstant.Request.PROXY_CLIENT_IP);
        }
        if (!isValidIp(ipAddress)) {
            ipAddress = request.getHeader(GlobalConstant.Request.WL_PROXY_CLIENT_IP);
        }
        if ((isValidIp(ipAddress))) {
            ipAddress = request.getHeader(GlobalConstant.Request.HTTP_CLIENT_IP);
        }
        if ((isValidIp(ipAddress))) {
            ipAddress = request.getHeader(GlobalConstant.Request.HTTP_X_FORWARDED_FOR);
        }
        if ((isValidIp(ipAddress))) {
            ipAddress = request.getRemoteAddr();
            if (StringUtils.equals(ipAddress, GlobalConstant.Request.LOCALHOST_IP) ||
                    StringUtils.equals(ipAddress, GlobalConstant.Request.LOCALHOST_IP_16)) {
                InetAddress inetAddress = null;
                try {
                    inetAddress = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    log.error("获取IP地址, 出现异常={}", e.getMessage(), e);
                }
                assert Objects.nonNull(inetAddress);
                ipAddress = inetAddress.getHostAddress();
            }
        }
        if (StringUtils.isNotBlank(ipAddress) && ipAddress.length() > GlobalConstant.Request.MAX_IP_LENGTH) {
            if (StringUtils.contains(ipAddress, GlobalConstant.Symbol.COMMA)) {
                ipAddress = StringUtils.substringBefore(ipAddress, GlobalConstant.Symbol.COMMA);
            }
        }
        return ipAddress;
    }

    /**
     * 获取当前登录用户
     *
     * @return
     */
    public static LoginUser currentUser() {
        LoginUser user = (LoginUser) ThreadContextHolder.get(GlobalConstant.Sys.CURRENT_LOGIN_USER);
        if (Objects.isNull(user)) {
            throw new BusinessException(ErrorType.UAC10010004);
        }
        return user;
    }

    /**
     * 获取请求头中的authorization信息
     *
     * @param request
     * @return
     */
    public static String getAuthHeader(HttpServletRequest request) {
        String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (StringUtils.isBlank(authHeader)) {
            throw new BusinessException(ErrorType.UAC10011040);
        }
        return authHeader;
    }

    /**
     * 解析header中的basic authentication token信息
     *
     * @param header
     * @return
     */
    public static String[] parseAuthHeader(String header) {
        byte[] base64Token = StringUtils.substring(header, 6).getBytes(Charsets.UTF_8);
        byte[] decode = Base64.getDecoder().decode(base64Token);
        String token = new String(decode, Charsets.UTF_8);
        if (!StringUtils.contains(token, GlobalConstant.Symbol.MH)) {
            throw new BadCredentialsException("Invalid basic authentication token");
        }
        return StringUtils.split(token, GlobalConstant.Symbol.MH);
    }

    /**
     * 是否为合法IP地址
     *
     * @param ipAddress
     * @return
     */
    private static boolean isValidIp(String ipAddress) {
        return StringUtils.isNotBlank(ipAddress) &&
                !StringUtils.equalsIgnoreCase(ipAddress, GlobalConstant.UNKNOWN);
    }

}
